package com.tping.lock.wait;

import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 等待 - 通知机制
 *
 */
public class GuardedQueue {

    private final Queue<Integer> staticQueue;


    public GuardedQueue(){
        this.staticQueue = new LinkedBlockingQueue<>();
    }

    /**
     * 获取资源
     * @return
     */
    public synchronized Integer get(){
        // 使其当前线程等待，让出执行权，也防止一直死循环，消耗资源
        // 这里使用while循环判断，避免假唤醒问题
        while ( staticQueue.isEmpty()){
            try {
                // 线程进入等待，并且释放锁资源
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        return staticQueue.peek();
    }

    public synchronized void put(Integer e){
        staticQueue.add(e);
        /**
         * 唤醒所有线程
         * 而不使用notify()方法是因为两个有区别，使用notify()方法存在有的线程会一直没有被唤醒的可能
         */
        notifyAll();
    }


    public static void main(String[] args) throws Exception {
        GuardedQueue guarded = new GuardedQueue();

        ExecutorService executorService = Executors.newFixedThreadPool(3);

        executorService.execute(() -> {
            Integer integer = guarded.get();
            System.out.println("线程：" + Thread.currentThread().getName() + "获取到值：" + integer);
        });

        //Thread.sleep(1000);

        executorService.execute(() -> {
            guarded.put(22);
        });

        executorService.shutdown();
        executorService.awaitTermination(30, TimeUnit.SECONDS);

    }


}
